#include "ads1299x.h"

// #include "esp_log.h"

// static const char *TAG = "m_ads";

uint8_t tx[3]={0};
uint8_t rx[3]={0};

uint8_t REG_CHnSET[8]={ADS1299_CH1SET_REG,ADS1299_CH2SET_REG,ADS1299_CH3SET_REG,ADS1299_CH4SET_REG,
    ADS1299_CH5SET_REG,ADS1299_CH6SET_REG,ADS1299_CH7SET_REG,ADS1299_CH8SET_REG};

/**
 * @brief chip select ADS1299 by pull low of its cs pin
 *
 * @warning None.
 *
 * @param  p_ads pointer of the specific ads1299_t instance;
 *
 * @return
 *     - None
 */
static void chip_select(ads1299_t * p_ads){
    if(p_ads->CS_PIN==PIN_NOT_USE) return;
    p_ads->pin_low(p_ads->CS_PIN);
}

/**
 * @brief chip unselect ADS1299 by pull high of its cs pin
 *
 * @warning None.
 *
 * @param  p_ads pointer of the specific ads1299_t instance;
 *
 * @return
 *     - None
 */
static void chip_unselect(ads1299_t * p_ads){
    if(p_ads->CS_PIN==PIN_NOT_USE) return;
    p_ads->pin_high(p_ads->CS_PIN);
}

/**
 * @brief  read ADS1299 certain register
 *
 * @warning None.
 *
 * @param  p_ads pointer of the specific ads1299_t instance;
 * @param  address the address of ADS1299 Register you are requesting;
 * @param  value the value you are want to write in;
 * 
 * @return 
 *      - the result of spi transfer.
 */
static int WRITE_ONE_REG(ads1299_t * p_ads,uint8_t address, uint8_t value){
    chip_select(p_ads);
    tx[0]=address | ADS1299_WRITE_REG_CMD; //  RREG expects 001rrrrr where rrrrr = address
    tx[1]=0x00;
    tx[2]=value;
    int r = p_ads->xfer(tx,rx,3);
    chip_unselect(p_ads);
    return r;
} 

/**
 * @brief  read ADS1299 certain register
 *
 * @warning None.
 *
 * @param  p_ads pointer of the specific ads1299_t instance;
 * @param  address the address of ADS1299 Register you are requesting;
 * @param  *out the value read from reg;
 *
 * @return 
 *      - the result of spi transfer.
 */
static int READ_ONE_REG(ads1299_t * p_ads,uint8_t address, uint8_t *out){
    chip_select(p_ads);
    tx[0]=address | ADS1299_READ_REG_CMD; //  RREG expects 001rrrrr where rrrrr = address
    tx[1]=0x00;
    tx[2]=0x00;
    int r = p_ads->xfer(tx,rx,3);
    chip_unselect(p_ads);
    *out = rx[2];
    return r;
}

/**
 * @brief  send a one byte CMD to ADS1299 
 *
 * @warning None.
 *
 * @param  p_ads pointer of the specific ads1299_t instance;
 * @param  cmd the cmd of you send to ADS1299;
 *
 * @return 
 *      - the result of spi transfer.
*/
static int SEND_CMD(ads1299_t * p_ads,uint8_t cmd){
    chip_select(p_ads);
    tx[0]=cmd;
    int r = p_ads->xfer(tx,rx,1);
    chip_unselect(p_ads);
    return r;
}

static void parse_id_reg(ads1299_t * p_ads, uint8_t regVal){
    p_ads->id.revId = (regVal & 0x10) >> 4;
    p_ads->id.devId = (regVal & 0x0C) >> 2;
    p_ads->id.nuCh  = (regVal & 0x03);

    // 2:8channels, 1:6channels, 0:4channels     
    if(p_ads->id.nuCh==2) p_ads->CH_NUM = 8;
    if(p_ads->id.nuCh==1) p_ads->CH_NUM = 6;
    if(p_ads->id.nuCh==0) p_ads->CH_NUM = 4;
}

void ads1299_get_id(ads1299_t * p_ads){
    SEND_CMD(p_ads,ADS1299_SDATAC_CMD);
    uint8_t regVal = 0;
    READ_ONE_REG(p_ads,ADS1299_ID_REG,&regVal);
    // regVal should be 0x3E
    parse_id_reg(p_ads,regVal);
}

void ads1299_get_leadoff_status(ads1299_t * p_ads,uint8_t * rx){
    // uint8_t reg_loff_p = 0;    // uint8_t reg_loff_n = 0;
    READ_ONE_REG(p_ads,ADS1299_LOFF_STATP_REG,&rx[0]);
    READ_ONE_REG(p_ads,ADS1299_LOFF_STATN_REG,&rx[1]);
}

void ads1299_init_hardware(ads1299_t * p_ads){
    p_ads->hardware_config();
}

void ads1299_stop_recording(ads1299_t * p_ads){
    p_ads->pin_low(p_ads->START_PIN);
    SEND_CMD(p_ads,ADS1299_SDATAC_CMD);
}

void ads_start_recording(ads1299_t * p_ads){
    // pass
}

void ads_start_by_start_pin(ads1299_t * p_ads){
    p_ads->pin_high(p_ads->START_PIN);
}


void ads1299_set_leadoff_detection(ads1299_t * p_ads){


}

void ads1299_setup(ads1299_t * p_ads){

    SEND_CMD(p_ads,ADS1299_RESET_CMD);
    p_ads->delay_ms(10);

    SEND_CMD(p_ads,ADS1299_SDATAC_CMD);
    p_ads->delay_ms(10);

    ads1299_get_id(p_ads);//get the channel number and set to the object
    p_ads->delay_ms(10);

    // WRITE_ONE_REG(p_ads,ADS1299_CONFIG1_REG, 0xF6); 
    // WRITE_ONE_REG(p_ads,ADS1299_CONFIG1_REG, 0xD5); 
    // WRITE_ONE_REG(p_ads,ADS1299_CONFIG1_REG, 0xD4); 
    //0xF6:1111 0110 : Multiple readback mode, Oscillator clock output enabled, 250SPS
    //0xD6:1101 0110 : Multiple readback mode, Oscillator clock output disabled, 250SPS
    //0xD5:1101 0101 : Multiple readback mode, Oscillator clock output disabled, 500SPS
    //0xD4:1101 0100 : Multiple readback mode, Oscillator clock output disabled, 1000SPS
    //0xF5:1111 0101 : Multiple readback mode, Oscillator clock output enabled, 500SPS

    if(p_ads->SMAPLE_RATE==SMAPLE_RATE_1000){
        WRITE_ONE_REG(p_ads,ADS1299_CONFIG1_REG, 0xD4); 
    }else if (p_ads->SMAPLE_RATE==SMAPLE_RATE_500){
        // WRITE_ONE_REG(p_ads,ADS1299_CONFIG1_REG, 0xD5);
        WRITE_ONE_REG(p_ads,ADS1299_CONFIG1_REG, 0xF5);         
    }else{ 
        // default is 250SPS
        WRITE_ONE_REG(p_ads,ADS1299_CONFIG1_REG, 0xD6); 
    }

    p_ads->delay_ms(1);

    // note here use test signal
    // WRITE_ONE_REG(p_ads,ADS1299_CONFIG2_REG, 0xD0); 
    // //0xD0:1101 0000 : Test signals are generated internally
    // //0xD5:1101 0101 : Test signals are generated internally, 2 × –(VREFP – VREFN) / 2400, Pulsed at fCLK / (2^20)

    if(p_ads->BIAS_BUFFER){
        WRITE_ONE_REG(p_ads,ADS1299_CONFIG3_REG, 0xEC); 
    }else{
        WRITE_ONE_REG(p_ads,ADS1299_CONFIG3_REG, 0xE0); 
    }
    //0xEC:1110 1100 : 
    //Enable internal reference buffer
    //BIASREF signal (AVDD + AVSS) / 2 generated internally
    //BIAS buffer is enabled

    //0xEC:1110 1100 : 
    //Enable internal reference buffer
    //BIASREF signal fed externally
    //BIAS buffer is powered down
    p_ads->delay_ms(1);

/* use only one  channels 
    WRITE_ONE_REG(p_ads,REG_CHnSET[0], 0x40); 
    WRITE_ONE_REG(p_ads,ADS1299_BIAS_SENSP_REG, 0x01);      
    p_ads->delay_ms(1);
    WRITE_ONE_REG(p_ads,ADS1299_BIAS_SENSN_REG, 0x01);      
    p_ads->delay_ms(1);
 */


/* use all channels */
    for(int ch=0;ch<p_ads->CH_NUM;ch++){        
        // note here use test signal
        // WRITE_ONE_REG(p_ads,REG_CHnSET[ch], 0x45);  
        WRITE_ONE_REG(p_ads,REG_CHnSET[ch], 0x40);  
        // WRITE_ONE_REG(p_ads,REG_CHnSET[ch], 0x60);  
        p_ads->delay_ms(1);    
    }
    //0x40:0100 0000 : PGA gain=8;Normal electrode input
    //0x60:0110 0000 : PGA gain=8;Normal electrode input
    //0x45:0100 0101 : PGA gain=8;Test signal

    WRITE_ONE_REG(p_ads,ADS1299_BIAS_SENSP_REG, 0xFF);      
    p_ads->delay_ms(1);
    WRITE_ONE_REG(p_ads,ADS1299_BIAS_SENSN_REG, 0x01);      
    // WRITE_ONE_REG(p_ads,ADS1299_BIAS_SENSN_REG, 0xFF);      
    p_ads->delay_ms(1);
    //0xFF: connect all inputs to BIAS    

    WRITE_ONE_REG(p_ads,ADS1299_MISC1_REG, 0x20);      
    //0x20: SRB1 Switches closed
    p_ads->delay_ms(1);


    // WRITE_ONE_REG(p_ads,ADS1299_LOFF_REG, 0x00);      
    // WRITE_ONE_REG(p_ads,ADS1299_LOFF_REG, 0xEC);      
    // WRITE_ONE_REG(p_ads,ADS1299_LOFF_REG, 0x13);      
    // WRITE_ONE_REG(p_ads,ADS1299_LOFF_REG, 0x0C);      
    // WRITE_ONE_REG(p_ads,ADS1299_LOFF_REG, 0x0D);      
    // WRITE_ONE_REG(p_ads,ADS1299_LOFF_REG, 0x0E);   
    // WRITE_ONE_REG(p_ads,ADS1299_LOFF_REG, 0x02);      
    // WRITE_ONE_REG(p_ads,ADS1299_LOFF_REG, 0x0E);      
    WRITE_ONE_REG(p_ads,ADS1299_LOFF_REG, 0x0C);      
    // p_ads->delay_ms(1);

    // uint8_t v = 0;    // uint8_t reg_loff_n = 0;
    // READ_ONE_REG(p_ads,ADS1299_LOFF_REG,&v);
    // printf(" --------------------- ------------------------ %x - - ",v);
    WRITE_ONE_REG(p_ads,ADS1299_CONFIG4_REG, 0x02);      
    p_ads->delay_ms(1);
    WRITE_ONE_REG(p_ads,ADS1299_LOFF_SENSP_REG, 0xFF);      
    p_ads->delay_ms(1);
    WRITE_ONE_REG(p_ads,ADS1299_LOFF_SENSN_REG, 0xFF);      
    p_ads->delay_ms(1);
    
}

void ads1299_setup_test_signal(ads1299_t * p_ads){
    SEND_CMD(p_ads,ADS1299_SDATAC_CMD);
    p_ads->delay_ms(1);   

    WRITE_ONE_REG(p_ads,ADS1299_CONFIG2_REG, 0xD0);  
    p_ads->delay_ms(1);   
}

void ads1299_set_RDATAC(ads1299_t * p_ads){
    SEND_CMD(p_ads,ADS1299_RDATAC_CMD);
    p_ads->delay_ms(1);   
}

uint8_t tx_buff_27_byte[DATA_PACKAGE_LEN]={0};
// make sure the rx buff longer than 27 bytes
// use this in RDATAC mode
void ads1299_get_data(ads1299_t * p_ads,uint8_t * rx){
    chip_select(p_ads);
    p_ads->xfer(tx_buff_27_byte,rx,DATA_PACKAGE_LEN);
    chip_unselect(p_ads);
}

int32_t convert_24bit_to_int(const uint8_t *bytes) {
    // 将3个字节组合成24位无符号整数（大端序）
    uint32_t raw_value = 0;

    raw_value = ((uint32_t)bytes[0] << 16) | 
                ((uint32_t)bytes[1] << 8)  | 
                (uint32_t)bytes[2];
    
    // 符号扩展：如果最高位（第23位）为1，则设置高8位为1，否则为0
    if (raw_value & 0x800000) { // 检查符号位
        return (int32_t)(raw_value | 0xFF000000); // 设置高8位为1
    } else {
        return (int32_t)raw_value; // 正数直接转换
    }
}


// int test_counter = 0;
// make sure the rx buff longer than 4*8 = 32 bytes, note ignore the status register data here
// use this in RDATAC mode
// 20251113 get the status, use rx_status, the rx_status should be a 3 byte array
void ads1299_drv_get_data_convert_int_array(ads1299_t * p_ads,int * rx_int,uint8_t* rx_status){
    uint8_t rx_buff_tmp[DATA_PACKAGE_LEN]={0}; // the raw data buff is 27 bytes

    chip_select(p_ads);
    p_ads->xfer(tx_buff_27_byte,rx_buff_tmp,DATA_PACKAGE_LEN);
    chip_unselect(p_ads);

    memcpy(rx_status,rx_buff_tmp,3);

    // test_counter++;

    // int offset = 0;
    for (int ch = 0; ch < 8; ch++){
        // offset = 3 + (ch) * 3;  
        // rx_int[ch] = convert_24bit_to_int(&rx_buff_tmp[offset]);     

        rx_int[ch] = convert_24bit_to_int(&rx_buff_tmp[3 + (ch) * 3]);
        // rx_int[ch] = test_counter;
        // rx_int[ch] = ch;
        // rx_int[ch] = ch*256;
        
    }
}



